package com.medical.data.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.medical.data.domain.*;
import com.medical.data.exception.MyException;
import com.medical.data.mapper.PatientTemplateMapper;
import com.medical.data.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medical.data.utils.ResultCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author cj
 * @since 2024-02-21
 */
@Service
public class PatientTemplateServiceImpl extends ServiceImpl<PatientTemplateMapper, PatientTemplate> implements PatientTemplateService {

    @Autowired
    private TokenSerivce tokenSerivce;

    @Autowired
    private ProjectTemplateService projectTemplateService;


    @Autowired
    private TemplateFormService templateFormService;

    @Autowired
    private FormDataService formDataService;

    @Autowired
    private FormTemplateService formTemplateService;

    @Autowired
    private FollowPatientService followPatientService;

    @Override
    public void addPatientTemplate(String projectId, String patientId) {
        User user = tokenSerivce.getUser();
        //首先查询该项目下该用户是否已经存在与节点之间的关系
        List<PatientTemplate> patientTemplates = baseMapper.selectList(Wrappers.<PatientTemplate>lambdaQuery()
                .eq(PatientTemplate::getPatientId, patientId)
                .eq(PatientTemplate::getDoctorId, user.getId())
                .eq(PatientTemplate::getProjectId, projectId).select(PatientTemplate::getId));
        if (!CollectionUtil.isEmpty(patientTemplates))
            throw new MyException(ResultCode.ERROR.getCode(), "该节点与患者之间已存在关系");
        //查询该项目下的节点
        List<FormTemplate> nodes = projectTemplateService.getAllNodes(projectId);
        if (CollectionUtil.isEmpty(nodes)) {
            throw new MyException(ResultCode.ERROR.getCode(), "该项目下没有节点，请新增节点");
        }
        //找到节点id
        List<String> nodeIds = nodes.stream().map(FormTemplate::getId).collect(Collectors.toList());
        //通过节点id找到表单
        Map<String, List<FormTemplate>> formTemplates = templateFormService.getForms(nodeIds);
        //新增数据
/*        PatientTemplate patientTemplate = new PatientTemplate().setProjectId(projectId).setDoctorId(user.getId())
                .setPatientId(patientId).setFinishNumber(0).setFinishNumberFormIdJson(JSONArray.toJSONString(new ArrayList<>()));*/
        for (Map.Entry<String, List<FormTemplate>> entry : formTemplates.entrySet()) {
            PatientTemplate patientTemplate = new PatientTemplate().setProjectId(projectId).setDoctorId(user.getId())
                    .setPatientId(patientId).setFinishNumber(0).setFinishNumberFormIdJson(JSONArray.toJSONString(new ArrayList<>()));
            patientTemplate.setTemplateId(entry.getKey());
            List<FormTemplate> formTemplates1 = Optional.of(entry.getValue()).orElse(new ArrayList<>());
            List<String> formTemplatesStr = formTemplates1.stream().map(FormTemplate::getId).collect(Collectors.toList());
            String formTemplatesJsonString = JSONArray.toJSONString(formTemplatesStr);
            patientTemplate.setNotFinishNumber(formTemplatesStr.size());
            patientTemplate.setNotFinishFormIdJson(formTemplatesJsonString);
            baseMapper.insert(patientTemplate);
        }
    }

    @Override
    public List<PatientTemplate> getProportionByNodeId(String nodeId, String doctorId, String projectId, String patientId) {
        List<PatientTemplate> patientTemplates = baseMapper.selectList(Wrappers.<PatientTemplate>lambdaQuery().eq(PatientTemplate::getPatientId, patientId)
                .eq(PatientTemplate::getTemplateId, nodeId)
                .eq(PatientTemplate::getDoctorId, doctorId)
                .eq(PatientTemplate::getProjectId, projectId)
        );
        return patientTemplates;
    }

    @Override
    public void updatePatientTemplate(String projectId, String patientId) {
        User user = tokenSerivce.getUser();
        //首先查询该项目下该用户是否已经存在与节点之间的关系
        List<PatientTemplate> patientTemplates = baseMapper.selectList(Wrappers.<PatientTemplate>lambdaQuery()
                .eq(PatientTemplate::getPatientId, patientId)
                .eq(PatientTemplate::getDoctorId, user.getId())
                .eq(PatientTemplate::getProjectId, projectId).select(PatientTemplate::getTemplateId));
        if (CollectionUtil.isEmpty(patientTemplates))
            throw new MyException(ResultCode.ERROR.getCode(), "该节点与患者之间没有存在关系");
        //查询该项目下的节点
//        List<FormTemplate> nodes = projectTemplateService.getNodesByProjectId(projectId);
//        if (CollectionUtil.isEmpty(nodes)){
//            throw new MyException(ResultCode.ERROR.getCode(), "该项目下没有节点，请新增节点");
//        }
        Map<String, PatientTemplate> patientTemplateMap = new HashMap<>();
        for (PatientTemplate patientTemplate : patientTemplates) {
            patientTemplateMap.put(patientTemplate.getTemplateId(), patientTemplate);
        }

        List<String> nodeIds = patientTemplates.stream().map(PatientTemplate::getTemplateId).collect(Collectors.toList());
        //找到节点id
//        List<String> nodeIds = nodes.stream().map(FormTemplate::getId).collect(Collectors.toList());
        //通过节点id找到表单
        Map<String, List<FormTemplate>> formTemplates = templateFormService.getForms(nodeIds);
        //新增数据
        PatientTemplate patientTemplate = new PatientTemplate().setProjectId(projectId).setDoctorId(user.getId())
                .setPatientId(patientId).setFinishNumber(0).setFinishNumberFormIdJson(JSONArray.toJSONString(new ArrayList<>()));
        for (Map.Entry<String, List<FormTemplate>> entry : formTemplates.entrySet()) {
            patientTemplate.setTemplateId(entry.getKey());
            List<FormTemplate> formTemplates1 = Optional.of(entry.getValue()).orElse(new ArrayList<>());
//            String formTemplatesJsonString = JSONArray.toJSONString(formTemplates1);
//            patientTemplate.setNotFinishNumber(formTemplates1.size());
//            patientTemplate.setNotFinishFormIdJson(formTemplatesJsonString);
//            baseMapper.insert(patientTemplate);
            if (CollectionUtil.isEmpty(formTemplates1))
                continue;
            //如果不为空
            List<String> ids = formTemplates1.stream().map(FormTemplate::getId).collect(Collectors.toList());
            List<FormData> formData = formDataService.getFormDataStatuByIds(ids, patientId, projectId);
            if (CollectionUtil.isEmpty(formData))
                continue;
            //如果不为空，判断一下status
            //将填充完成的添加进去
            Set<String> finishSet = new HashSet<>();
            List<String> idsToRemove = new ArrayList<>();
            for (FormData item : formData) {
                if (item.getStatus()) {
                    String formId = item.getFormId();
                    finishSet.add(formId);
                    idsToRemove.add(formId);
                }
            }
            ids.removeAll(idsToRemove);
            List<String> finish = new ArrayList<>(finishSet);
            PatientTemplate patientTemplate1 = patientTemplateMap.get(entry.getKey());
            LambdaQueryWrapper<PatientTemplate> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(PatientTemplate::getPatientId, patientId)
                    .eq(PatientTemplate::getProjectId, projectId)
                    .eq(PatientTemplate::getTemplateId, patientTemplate1.getTemplateId());
            PatientTemplate patientTemplate2 = baseMapper.selectOne(wrapper);
            patientTemplate2.setNotFinishNumber(ids.size());
            //TODO  这里就是需要去就随访患者表中的状态修改，同时不能修改普通表单只能是随访节点
            //TODO  先查询notFinish为0的节点，再去查找他是否为随访节点，如果是随访节点且未完成表单的数量为0，则更新随访患者表里的完成状态
            if (ids.size() == 0) {
                String nodeId = patientTemplate1.getTemplateId();
                //更新随访患者表中的状态
                if (formTemplateService.isFollowUp(nodeId)) {
                    followPatientService.updateStatus(nodeId, patientId);
                }
            }
            patientTemplate2.setFinishNumber(finish.size());
            patientTemplate2.setFinishNumberFormIdJson(JSONArray.toJSONString(Optional.of(finish).orElse(new ArrayList<>())));
            patientTemplate2.setNotFinishFormIdJson(JSONArray.toJSONString(Optional.of(ids).orElse(new ArrayList<>())));
            int insert = baseMapper.updateById(patientTemplate2);
            if (insert < 1) {
                throw new MyException(ResultCode.ERROR.getCode(), "更新patient_template表失败");
            }
            //查询未完成的
        }
    }

    @Override
    public void updateNoFinish(String projectId, String templateId, String formId) {
        //先判断template是否存在
        LambdaQueryWrapper<PatientTemplate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PatientTemplate::getTemplateId, templateId)
                .eq(PatientTemplate::getProjectId, projectId);
        List<PatientTemplate> patientTemplates = new ArrayList<>();
        patientTemplates = this.baseMapper.selectList(wrapper);
        if (ObjectUtils.isEmpty(patientTemplates)) {
            throw new MyException(ResultCode.ERROR.getCode(), "templateId传递错误");
        }

        for (PatientTemplate patientTemplate : patientTemplates) {
            // 对每个元素的NotFinishNumber进行加一操作
            int notFinishNumber = patientTemplate.getNotFinishNumber();
            patientTemplate.setNotFinishNumber(notFinishNumber + 1);

            // 将formId添加到NotFinishNumberFormIdJson中
            JSONArray formIdArray = JSON.parseArray(patientTemplate.getNotFinishFormIdJson());
            formIdArray.add(formId);
            patientTemplate.setNotFinishFormIdJson(formIdArray.toJSONString());
            // 更新数据库中的数据
            int updateResult = this.baseMapper.updateById(patientTemplate);
            if (updateResult < 1) {
                throw new MyException(ResultCode.ERROR.getCode(), "更新失败");
            }
        }
    }

    @Override
    public String getProjectByPatient(String patientId) {
        LambdaQueryWrapper<PatientTemplate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PatientTemplate::getPatientId, patientId);
        List<PatientTemplate> patientTemplates = this.baseMapper.selectList(wrapper);
        return patientTemplates.get(0).getProjectId();
    }

    @Override
    public List<String> getPatientByNode(String nodeId) {
        LambdaQueryWrapper<PatientTemplate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PatientTemplate::getTemplateId, nodeId);
        List<PatientTemplate> lists = new ArrayList<>();
        lists = this.baseMapper.selectList(wrapper);
        List<String> stringList = new ArrayList<>();
        for (PatientTemplate patientTemplate : lists) {
            stringList.add(patientTemplate.getPatientId());
        }
        return stringList;
    }

    @Override
    public void deletePatientTemplateById(String patientId) {
        LambdaQueryWrapper<PatientTemplate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PatientTemplate::getPatientId, patientId);
        int delete = this.baseMapper.delete(wrapper);
        if (delete < 1) {
            throw new MyException(ResultCode.ERROR.getCode(), "删除患者节点表数据失败");
        }
    }

    @Override
    public void deleteNodeById(String nodeId) {
        LambdaQueryWrapper<PatientTemplate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PatientTemplate::getTemplateId, nodeId);
        List<PatientTemplate> patientTemplates = this.baseMapper.selectList(wrapper);
        if (patientTemplates.size() != 0) {
            int delete = this.baseMapper.delete(wrapper);
            if (delete < 1) {
                throw new MyException(ResultCode.ERROR.getCode(), "删除患者节点表数据失败");
            }
        }

    }

    @Override
    public void updateFormStatus(String pId, String formId) {
        LambdaQueryWrapper<PatientTemplate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PatientTemplate::getTemplateId, pId);
        List<PatientTemplate> patientTemplates = this.baseMapper.selectList(wrapper);
        for (PatientTemplate patientTemplate : patientTemplates) {
            LambdaUpdateWrapper<PatientTemplate> wrapper1 = new LambdaUpdateWrapper<>();
            wrapper1.eq(PatientTemplate::getId, patientTemplate.getId());
            String jsonStr1 = patientTemplate.getFinishNumberFormIdJson();
            String jsonStr2 = patientTemplate.getNotFinishFormIdJson();
            JSONArray jsonArray1 = new JSONArray(jsonStr1);
            JSONArray jsonArray2 = new JSONArray(jsonStr2);
            JSONArray newJsonArray1 = new JSONArray();

            int finishNumberNow = patientTemplate.getFinishNumber();
            int noFinishNumberNow = patientTemplate.getNotFinishNumber();
            for (int i = 0; i < jsonArray1.size(); i++) {
                String idInJson1 = jsonArray1.getString(i);
                if (!idInJson1.equals(formId)) { // 如果不等于formId，则添加到新数组中
                    newJsonArray1.add(idInJson1);
                    finishNumberNow--;
                }
                jsonStr1 = newJsonArray1.toString();
            }

            for (int i = 0; i < jsonArray2.size(); i++) {
                String idInJson2 = jsonArray2.getString(i);
                if (!idInJson2.equals(formId)) { // 如果不等于formId，则添加到新数组中
                    newJsonArray1.add(idInJson2);
                    noFinishNumberNow--;
                }
                jsonStr2 = newJsonArray1.toString();
            }

            wrapper1.set(PatientTemplate::getFinishNumberFormIdJson, jsonStr1);
            wrapper1.set(PatientTemplate::getNotFinishFormIdJson, jsonArray2);
            wrapper1.set(PatientTemplate::getFinishNumber, finishNumberNow);
            wrapper1.set(PatientTemplate::getNotFinishNumber, noFinishNumberNow);

            int update = this.baseMapper.update(null, wrapper);
            if (update < 1) {
                throw new MyException(ResultCode.ERROR.getCode(), "更新患者节点表失败");
            }
        }

    }

    @Override
    public Double getFinishStatus(String patientId, String nodeId) {
        LambdaQueryWrapper<PatientTemplate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PatientTemplate::getPatientId, patientId)
                .eq(PatientTemplate::getTemplateId, nodeId);
        PatientTemplate patientTemplate = this.baseMapper.selectOne(wrapper);
        double count;
        if (patientTemplate.getFinishNumber() + patientTemplate.getNotFinishNumber() == 0) {
            count = 0.0;
        } else {
            count = patientTemplate.getFinishNumber() * 1.0 / (patientTemplate.getFinishNumber() + patientTemplate.getNotFinishNumber());

        }
        return count;
    }

}
